.nf
.bp 1
                                                    Appendix B

                                                 A Skeletal CBIOS




  1                       ;        skeletal cbios for first level of cp/m 2.0 alteration
  2                       ;
  3      0014 =           msize    equ    20             ;cp/m version memory size in kilobytes
  4                       ;
  5                       ;        "bias" is address offset from 3400h for memory systems
  6                       ;        than 16k (referred to as "b" throughout the text)
  7                       ;
  8      0000 =           bias     equ    (msize-20)*1024
  9      3400 =           ccp      equ    3400h+bias     ;base of ccp
 10      3c06 =           bdos     equ    ccp+806h       ;base of bdos
 11      4a00 =           bios     equ    ccp+1600h      ;base of bios
 12      0004 =           cdisk    equ    0004h          ;current disk number 0=a,..., 15=p
 13      0003 =           iobyte   equ    0003h          ;intel i/o byte
 14                       ;      
 15      4a00                      org    bios           ;origin of this program
 16      002c =           nsects   equ    ($-ccp)/128    ;warm start sector count
 17                       ;
 18                       ;        jump vector for individual subroutines
 19      4a00 c39c4a               jmp    boot           ;cold start
 20      4a03 c3a64a      wboote:  jmp    wboot          ;warm start
 21      4a06 c3114b               jmp    const          ;console status
 22      4a09 c3244b               jmp    conin          ;console character in
 23      4a0c c3374b               jmp    conout         ;console character out
 24      4a0f c3494b               jmp    list           ;list character out
 25      4a12 c34d4b               jmp    punch          ;punch character out
 26      4a15 c34f4b               jmp    reader         ;reader character out
 27      4a18 c3544b               jmp    home           ;move head to home position
 28      4a1b c35a4b               jmp    seldsk         ;select disk
 29      4a1e c37d4b               jmp    settrk         ;set track number
 30      4a21 c3924b               jmp    setsec         ;set sector number
 31      4a24 c3ad4b               jmp    setdma         ;set dma address
 32      4a27 c3c34b               jmp    read           ;read disk
 33      4a2a c3d64b               jmp    write          ;write disk
 34      4a2d c34b4b               jmp    listst         ;return list status
 35      4a30 c3a74b               jmp    sectran        ;sector translate
 36                       ;
 37                       ;        fixed data tables for four-drive standard
 38                       ;        ibm-compatible 8" disks
 39                       ;        disk parameter header for disk 00
 40      4a33 734a0000    dpbase:  dw     trans, 0000h
 41      4a37 00000000             dw     0000h, 0000h
 42      4a3b f04c8d4a             dw     dirbf, dpblk
 43      4a3f ec4d704d             dw     chk00, all00
 44                       ;        disk parameter header for disk 01
 45      4a43 734a0000             dw     trans, 0000h
 46      4a47 00000000             dw     0000h, 0000h
 47      4a4b f04c8d4a             dw     dirbf, dpblk
 48      4a4f fc4d8f4d             dw     chk01, all01
 49                       ;        disk parameter header for disk 02
 50      4a53 734a0000             dw     trans, 0000h
 51      4a57 00000000             dw     0000h, 0000h
 52      4a5b f04c8d4a             dw     dirbf, dpblk
 53      4a5f 0c4eae4d             dw     chk02, all02
 54                       ;        disk parameter header for disk 03
 55      4a63 734a0000             dw     trans, 0000h
 56      4a67 00000000             dw     0000h, 0000h
 57      4a6b f04c8d4a             dw     dirbf, dpblk
 58      4a6f 1c4ecd4d             dw     chk03, all03
 59                       ;
 60                       ;        sector translate vector
 61      4a73 01070d13    trans:   db     1, 7, 13, 19   ;sectors 1, 2, 3, 4
 62      4a77 19050b11             db     25, 5, 11, 17  ;sectors 5, 6, 7, 8
 63      4a7b 1703090f             db     23, 3, 9, 15   ;sectors 9, 10, 11, 12
 64      4a7f 1502080e             db     21, 2, 8, 14   ;sectors 13, 14, 15, 16
 65      4a83 141a060c             db     20, 26, 6, 12  ;sectors 17, 18, 19, 20
 66      4a87 1218040a             db     18, 24, 4, 10  ;sectors 21, 22, 23, 24
 67      4a8b 1016                 db     16, 22         ;sectors 25, 26
 68                       ;
 69                       dpblk:   ;disk parameter block, common to all disks
 70      4a8d 1a00                 dw     26             ;sectors per track
 71      4a8f 03                   db     3              ;block shift factor
 72      4a90 07                   db     7              ;block mask
 73      4a91 00                   db     0              ;null mask
 74      4a92 f200                 dw     242            ;disk size-1
 75      4a94 3f00                 dw     63             ;directory max
 76      4a96 c0                   db     192            ;alloc 0
 77      4a97 00                   db     0              ;alloc 1
 78      4a98 1000                 dw     16             ;check size
 79      4a9a 0200                 dw     2              ;track offset
 80                       ;
 81                       ;        end of fixed tables
 82                       ;
 83                       ;        individual subroutines to perform each function
 84                       boot:    ;simplest case is to just perform parameter initialization
 85      4a9c af                   xra    a              ;zero in the accum
 86      4a9d 320300               sta    iobyte         ;clear the iobyte
 87      4aa0 320400               sta    cdisk          ;select disk zero
 88      4aa3 c3ef4a               jmp    gocpm          ;initialize and go to cp/m
 89                       ;
 90                       wboot:   ;simplest case is to read the disk until all sectors loaded
 91      4aa6 318000               lxi    sp, 80h        ;use space below buffer for stack
 92      4aa9 0e00                 mvi    c, 0           ;select disk 0
 93      4aab cd5a4b               call   seldsk
 94      4aae cd544b               call   home           ;go to track 00
 95                       ;
 96      4ab1 062c                 mvi    b, nsects      ;b counts # of sectors to load
 97      4ab3 0e00                 mvi    c, 0           ;c has the current track number
 98      4ab5 1602                 mvi    d, 2           ;d has the next sector to read
 99                       ;        note that we begin by reading track 0, sector 2 since sector 1
100                       ;        contains the cold start loader, which is skipped in a warm start
101      4ab7 210034               lxi    h, ccp         ;base of cp/m (initial load point)
102                       load1:   ;load one more sector
103      4aba c5                   push   b              ;save sector count, current track
104      4abb d5                   push   d              ;save next sector to read
105      4abc e5                   push   h              ;save dma address
106      4abd 4a                   mov    c, d           ;get sector address to register c
107      4abe cd924b               call   setsec         ;set sector address from register c
108      4ac1 c1                   pop    b              ;recall dma address to b, c
109      4ac2 c5                   push   b              ;replace on stack for later recall
110      4ac3 cdad4b               call   setdma         ;set dma address from b, c
111                       ; 
112                       ;        drive set to 0, track set, sector set, dma address set
113      4ac6 cdc34b               call   read
114      4ac9 fe00                 cpi    00h            ;any errors?
115      4acb c2a64a               jnz    wboot          ;retry the entire boot if an error occurs
116                       ;        
117                       ;        no error, move to next sector
118      4ace e1                   pop    h              ;recall dma address
119      4acf 118000               lxi    d, 128         ;dma=dma+128
120      4ad2 19                   dad    d              ;new dma address is in h, l
121      4ad3 d1                   pop    d              ;recall sector address
122      4ad4 c1                   pop    b              ;recall number of sectors remaining, and current trk
123      4ad5 05                   dcr    b              ;sectors=sectors-1
124      4ad6 caef4a               jz     gocpm          ;transfer to cp/m if all have been loaded
125                       ;
126                       ;        more sectors remain to load, check for track change
127      4ad9 14                   inr    d
128      4ada 7a                   mov    a,d            ;sector=27?, if so, change tracks
129      4adb fe1b                 cpi    27
130      4add daba4a               jc     load1          ;carry generated if sector<27
131                       ;
132                       ;        end of current track, go to next track
133      4ae0 1601                 mvi    d, 1           ;begin with first sector of next track
134      4ae2 0c                   inr    c              ;track=track+1
135                       ;
136                       ;        save register state, and change tracks
137      4ae3 c5                   push   b
138      4ae4 d5                   push   d
139      4ae5 e5                   push   h
140      4ae6 cd7d4b               call   settrk         ;track address set from register c
141      4ae9 e1                   pop    h
142      4aea d1                   pop    d
143      4aeb c1                   pop    b
144      4aec c3ba4a               jmp    load1          ;for another sector
145                       ;
146                       ;        end of load operation, set parameters and go to cp/m
147                       gocpm:
148      4aef 3ec3                 mvi    a, 0c3h        ;c3 is a jmp instruction
149      4af1 320000               sta    0              ;for jmp to wboot
150      4af4 21034a               lxi    h, wboote      ;wboot entry point
151      4af7 220100               shld   1              ;set address field for jmp at 0
152                       ;
153      4afa 320500               sta    5              ;for jmp to bdos
154      4afd 21063c               lxi    h, bdos        ;bdos entry point
155      4b00 220600               shld   6              ;address field of jump at 5 to bdos
156                       ;
157      4b03 018000               lxi    b, 80h         ;default dma address is 80h
158      4b06 cdad4b               call   setdma
159                       ;
160      4b09 fb                   ei                    ;enable the interrupt system
161      4b0a 3a0400               lda    cdisk          ;get current disk number
162      4b0d 4f                   mov    c, a           ;send to the ccp
163      4b0e c30034               jmp    ccp            ;go to cp/m for further processing
164                       ;
165                       ;
166                       ;        simple i/o handlers (must be filled in by user)
167                       ;        in each case, the entry point is provided, with space reserved
168                       ;        to insert your own code
169                       ; 
170                       const:   ;console status, return 0ffh if character ready, 00h if not
171      4b11                      ds     10h            ;space for status subroutine
172      4b21 3e00                 mvi    a, 00h
173      4b23 c9                   ret
174                       ;
175                       conin:   ;console character into register a
176      4b24                      ds     10h            ;space for input routine
177      4b34 e67f                 ani    7fh            ;strip parity bit
178      4b36 c9                   ret
179                       ;
180                       conout:  ;console character output from register c
181      4b37 79                   mov    a, c           ;get to accumulator
182      4b38                      ds     10h            ;space for output routine
183      4b48 c9                   ret
184                       ;
185                       list:    ;list character from register c
186      4b49 79                   mov    a, c           ;character to register a
187      4b4a c9                   ret                   ;null subroutine
188                       ;
189                       listst:  ;return list status (0 if not ready, 1 if ready)
190      4b4b af                   xra    a              ;0 is always ok to return
191      4b4c c9                   ret
192                       ;
193                       punch:   ;punch character from register c
194      4b4d 79                   mov    a, c           ;character to register a
195      4b4e c9                   ret                   ;null subroutine
196                       ;
197                       ;
198                       reader:  ;reader character into register a from reader device
199      4b4f 3e1a                 mvi    a, 1ah         ;enter end of file for now (replace later)
200      4b51 e67f                 ani    7fh            ;remember to strip parity bit
201      4b53 c9                   ret     
202                       ;
203                       ;
204                       ;        i/o drivers for the disk follow
205                       ;        for now, we will simply store the parameters away for use
206                       ;        in the read and write subroutines
207                       ;
208                       home:    ;move to the track 00 position of current drive
209                       ;        translate this call into a settrk call with parameter 00
210      4b54 0e00                 mvi    c, 0           ;select track 0
211      4b56 cd7d4b               call   settrk
212      4b59 c9                   ret                   ;we will move to 00 on first read/write
213                       ;
214                       seldsk:  ;select disk given by register c
215      4b51 210000               lxi    h, 0000h       ;error return code
216      4b5d 79                   mov    a, c
217      4b5e 32ef4c               sta    diskno
218      4b61 fe04                 cpi    4              ;must be between 0 and 3
219      4b63 d0                   rnc                   ;no carry if 4, 5,...
220                       ;        disk number is in the proper range
221      4b64                      ds     10             ;space for disk select
222                       ;        compute proper disk parameter header address
223      4b6e 3aef4c               lda    diskno
224      4b71 6f                   mov    l, a           ;l=disk number 0, 1, 2, 3
225      4b72 2600                 mvi    h, 0           ;high order zero
226      4b74 29                   dad    h              ;*2
227      4b75 29                   dad    h              ;*4
228      4b76 29                   dad    h              ;*8
229      4b77 29                   dad    h              ;*16 (size of each header)
230      4b78 11334a               lxi    d, dpbase
231      4b7b 19                   dad    0              ;hl=.dpbase (diskno*16)
232      4b7c c9                   ret
233                       ;
234                       settrk:  ;set track given by register c
235      4b7d 79                   mov    a, c
236      4b7e 32e94c               sta    track
237      4b81                      ds     10h            ;space for track select
238      4b91 c9                   ret
239                       ;
240                       setsec:  ;set sector given by register c
241      4b92 79                   mov    a, c
242      4b93 32eb4c               sta    sector
243      4b96                      ds     10h            ;space for sector select
244      4ba6 c9                   ret
245                       ;
246                       sectran:
247                                ;translate the sector given by bc using the
248                                ;translate table given by de
249      4ba7 eb                   xchg                  ;hl=.trans
250      4ba8 09                   dad    b              ;hl=.trans (sector)
251      4ba9 6e                   mov    l, m           ;l=trans (sector)
252      4baa 2600                 mvi    h, 0           ;hl=trans (sector)
253      4bac c9                   ret                   ;with value in hl
254                       ;
255                       setdma:  ;set dma address given by registers b and c
256      4bad 69                   mov    l, c           ;low order address
257      4bae 60                   mov    h, b           ;high order address
258      4baf 22ed4c               shld   dmaad          ;save the address
259      4bb2                      ds     10h            ;space for setting the dma address
260      4bc2 c9                   ret
261                       ;
262                       read:    ;perform read operation (usually this is similar to write
263                       ;        so we will allow space to set up read command, then use
264                       ;        common code in write)
265      4bc3                      ds     10h            ;set up read command
266      4bd3 c3e64b               jmp    waitio         ;to perform the actual i/o
267                       ;
268                       write:   ;perform a write operation
269      4bd6                      ds     10h            ;set up write command
270                       ;
271                       waitio:  ;enter here from read and write to perform the actual i/o
272                       ;        operation. return a 00h in register a if the operation completes
273                       ;        properly, and 01h if an error occurs during the read or write
274                       ;
275                       ;        in this case, we have saved the disk number in 'diskno' (0, 1)
276                       ;                              the track number in 'track' (0-76)
277                       ;                              the sector number in 'sector' (1-26)
278                       ;                              the dma address in 'dmaad' (0-65535)
279      4be6                      ds     256            ;space reserved for i/o drivers
280      4ce6 3e01                 mvi    a, 1           ;error condition
281      4ce8 c9                   ret                   ;replaced when filled-in
282                       ;
283                       ;        the remainder of the cbios is reserved uninitialized
284                       ;        data area, and does not need to be a part of the
285                       ;        system memory image (the space must be available,
286                       ;        however, between "begdat" and "enddat").
287                       ;
288      4ce9             track:   ds     2              ;two bytes for expansion
289      4ceb             sector:  ds     2              ;two bytes for expansion
290      4ced             dmaad:   ds     2              ;direct memory address
291      4cef             diskno:  ds     1              ;disk number 0-15
292                       ;
293                       ;        scratch ram area for bdos use
294      4cf0=            begdat   equ    $              ;beginning of data area
295      4cf0             dirfb:   ds     128            ;scratch directory area
296      4d70             all00:   ds     31             ;allocation vector 0
297      4d8f             all01:   ds     31             ;allocation vector 1
298      4dae             all02:   ds     31             ;allocation vector 2
299      4dcd             all03:   ds     31             ;allocation vector 3
300      4dec             chk00:   ds     16             ;check vector 0
301      4dfc             chk01:   ds     16             ;check vector 1
302      4e0c             chk02:   ds     16             ;check vector 2
303      4e1c             chk03:   ds     16             ;check vector 3
304                       ;
305      4e2c             enddat   equ    $              ;end of data area
306      013c=            datsiz   equ    $-begdat;      ;size of data area
307      4e2c                      end

all00          4d70      43     296#
all01          4d8f      48     297#
all02          4dae      53     298#
all03          4dcd      58     299#
bdos           3c06      10#    154
begdat         4cf0     294#    306
bias           0000       8#      9
bios           4a00      11#     15
boot           4a9c      19      84#
ccp            3400       9#     10      11      16     101     163
cdisk          0004      12#     87     161
chk00          4dec      43     300#
chk01          4dfc      48     301#
chk02          4e0c      53     302#
chk03          4e1c      58     303#
conin          4b24      22     175#
conout         4b37      23     180#
const          4b11      21     170#
datsiz         013c     306#
dirbf          4cf0      42      47      52      57     295#
diskno         4cef     217     223     291#
dmaad          4ced     258     290#
dpbase         4a33      40#    230
dpblk          4a8d      42      47      52      57      69#
enddat         4e2c     305#
gocpm          4aef      88     124     147#
home           4b54      27      94     208#
iobyte         0003      13#     86
list           4b49      24     185#
listst         4b4b      34     189#
load1          4aba     102#    130     144
msize          0014       3#      8
nsects         002c      16#     96
punch          4b4d      25     193#
read           4bc3      32     113     262#
reader         4b4f      26     198#
sector         4ceb     242     289#
sectran        4ba7      35     246#
seldsk         4b5a      28      93     214#
setdma         4bad      31     110     158     255#
setsec         4b92      30     107     240#
settrk         4b7d      29     140     211     234#
track          4ce9     236     288#
trans          4a73      40      45      50      55      61#
waitio         4be6     266     271#
wboot          4aa6      20      90#    115
wboote         4a03      20#    150
write          4bd6      33     268#


.nx appc
